package pl.edu.mimuw.irs.rcp.persistence.descriptor;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;

import pl.edu.mimuw.irs.rcp.persistence.IExternalResource;
import pl.edu.mimuw.irs.rcp.persistence.resource.HistoryLoader;

public class HistoryFilesDescriptor implements IExternalResource {

	public static final String NAME = "history references";
	
	// *** Properties
	
	public static final String PROPERTY_FILES = "PROPERTY_FILES";
	
	// *** Attributes

	private IProject project;
	private transient PropertyChangeSupport listeners;
	public IProject getProject() {
		return project;
	}
	public PropertyChangeSupport getListeners() {
		if (listeners == null) listeners = new PropertyChangeSupport(this);
		return listeners;
	}
	@Override
	public String getName() {
		return NAME;
	}
	
	// *** Methods
	
	public HistoryFilesDescriptor(IProject project) {
		this.project = project;
	}
	
	public void addFile(File file) throws Exception {
		List<File> files = getFiles();
		files.add(file);
		setFiles(files);
		getProject().touch(null);
	}
	
	public void removeFile(File file) throws Exception {
		List<File> files = getFiles();
		files.remove(file);
		setFiles(files);
		getProject().touch(null);
	}
	
	public void setFiles(List<File> files) throws Exception {
		List<File> oldFiles = getFiles();
		if (project == null) return;
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		try {
			new FileContainerPersistence().writeToStream(files, output); // XXX : dirty
			project.setPersistentProperty(HistoryLoader.HISTORY_PATHS, output.toString("UTF-8"));
			getListeners().firePropertyChange(PROPERTY_FILES, oldFiles, files);
		} catch (CoreException e) {
		}
	}
	
	public List<File> getFiles() throws Exception {
		if (project == null) return new LinkedList<File>();
		String contents = null;
		try {
			contents = project.getPersistentProperty(HistoryLoader.HISTORY_PATHS);
		} catch (CoreException e) {
		}
		if (contents == null) return new LinkedList<File>();
		return parseContents(contents);
	}
	
	public List<HistoryFileDescriptor> getFilesDescriptors() throws Exception {
		List<File> files = getFiles();
		List<HistoryFileDescriptor> descriptors = 
			new ArrayList<HistoryFileDescriptor>(files.size());
		for (File file : files) {
			descriptors.add(new HistoryFileDescriptor(this, file));
		}
		return descriptors;
	}

	protected List<File> parseContents(String contents) throws Exception {
		InputStream input = new ByteArrayInputStream(contents.getBytes());
		List<File> files = null;
		files = new FileContainerPersistence().loadFromStream(input);

		if (files == null) return Collections.emptyList();
		return files;
	}
	
	@Override
	public Object[] getChildren() throws Exception {
		return getFilesDescriptors().toArray();
	}
	
	@Override
	public Object getParent() {
		return getProject();
	}
	
	public void addPropertyChangeListener(PropertyChangeListener listener) {
		getListeners().addPropertyChangeListener(listener);
	}
	
	public void removePropertyChangeListener(PropertyChangeListener listener) {
		getListeners().removePropertyChangeListener(listener);
	}
}
